module necrophilia.skeleton.Sectors;

// TODO remove .dup where not necessery
class SectoredView(Anim){
	protected Sector!(Anim)[char[]] sectors;
	protected char[][][char[]] groups;

	this(){
		
	}
	
	this(char[][] sectors){
		foreach(sector; sectors){
			this.sectors[sector]=new Sector!(Anim);
		}
	}
	
	void addGroup(char[] name, char[][] members){
		foreach(member;members){
			groups[name.dup]~=member;
		}
	}
	
	void allocate(Anim newanim){
		char[][] sectors = newanim.sectors;
		
		foreach(sector; sectors){
			if((sector in this.sectors) !is null) {
				this.sectors[sector].occupy(newanim, this);
				continue;
			}
			
			if(sector in this.groups){
				foreach(member; groups[sector]){
						assert ( member in groups !is null, member);
						this.sectors[member].free();
				}
				continue;
			}
			
			assert(false, sector);
		}
	}
	
	void free(char[][] sectors){
		foreach(sector; sectors){
			if((sector in this.sectors) !is null) {
				this.sectors[sector].free();
				continue;
			}
			
			if(sector in this.groups){
				foreach(member; groups[sector]){
						assert ( member in groups !is null, member);
						this.sectors[member].free();
				}
				continue;
			}
			
			assert(false, sector);
		}
	}
	
	SectoredView!(Anim) clone(){
		auto twin=new SectoredView!(Anim)();
		foreach(key; this.sectors.keys){
			twin.sectors[key.dup]=new Sector!(Anim);
		}
		
		foreach(key; this.groups.keys){
			twin.groups[key.dup]= this.groups[key].dup;
		}
		return twin;
	}
}

class Sector(Anim){
	protected Anim occupant=null; 
	
	void free(){
		occupant=null;
	}
	
	void occupy(Anim anim, SectoredView!(Anim) owner){
		if(occupant !is null){
			occupant.freeSectors(owner);
		}
		occupant=anim;
	}
}